using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;



using CStock;
using CUtil;

namespace CStock
{
	/// <summary>
	/// Summary description for QuoteWriter.
	/// </summary>
	public class QuoteWriter
	{
		IProgramContext programContext;
		IProgramContext programContextUpdate;


		//private static string DefaultShareQuoteFileExtension = "";
		private static char defaultExportDelimiter = ',';
		
		//private static string currentExportDelimiter ;

		
		
		public QuoteWriter(IProgramContext programContext)
		{
			
			this.programContext = programContext;

            
            string myID = "QuoteUpdate";
            string myPath = this.programContext.Configuration.Directories.ApplicationPath + "\\Data\\" + myID;
            this.programContextUpdate = CStock.ProgramContext.CreateProgramContext(myPath, myID, false);

			
			
		}
		public IProgramContext ProgramContextUpdate
		{
			get
			{
				return this.programContextUpdate;
			}
			
		}

		/// <summary>
		/// WriteQuotesToFile
		/// </summary>
		/// <param name="parStreamWriter"></param>
		public static void WriteQuotesToFile(IDataClass dci)
		{
			DataClassDaily dc = dci as DataClassDaily;
			Debug.Assert(dc != null, "Error writing quotes with " + dci.ID);
			if(dc == null) 
				return;

			System.IO.StreamWriter swriter = null;
			try
			{
				string longFileName = dc.Path + "\\" + dc.ID;
				//find the path - for eventually creating directories
				string[] pathArray= longFileName.Split(new char[]{'\\'},100);
				//Get pure file name
				string shortfileName = pathArray[pathArray.GetLength(0) -1 ];
				string path = longFileName.Remove(longFileName.Length - shortfileName.Length,shortfileName.Length);

				//eventually create path
				if(path != string.Empty)
				{
					CUtil.DirectoryUtil.CreateDirectory(path);
				}

				//create stream writer
				string fileName = dc.Path + "\\" + dc.ID;
				swriter = new System.IO.StreamWriter(fileName , false);
				
				//write the quotes
				WriteQuotesToStream(dc , swriter);
				
				
			}
			catch (Exception exc)
			{
				Debug.Assert(false,"Error writing ExportShareContent" + exc.Message);
			}
			if (swriter != null)
			{
				swriter.Close();
			}
		}
		public static void WriteQuotesToStream(DataClassDaily dc,System.IO.StreamWriter swriter)
		{
			try
			{
			
				IListQuotes qColl = dc.QuoteCollection;
				string str ;
				for (int i=0; i < qColl.Count; i++)
				{
					IQuote qu = (IQuote)qColl[i];
					if (qu != null)
					{
						//Debug.WriteLine("Taipan Import CreateQuoteContent Start: " + dc.Name + ":(" + i + " von " + locOHLCCount + ") " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
						str = GetQuoteAsString(qu);
						swriter.WriteLine(str);
						//Debug.WriteLine("Taipan Import CreateQuoteContent End: " + dc.Name + ":(" + i + " von " + locOHLCCount + ") " + DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString());
					}
					
					//this.localStringBuilder.AddString(null,locQuoteString,DelimiterUtil.CRLFFile);
				}
				
			}
			catch (Exception exc)
			{
				System.Diagnostics.Debug.WriteLine("Error creating ExportQuoteListContent: " + exc.Message);
			}
			
		}
		/// <summary>
		/// GetQuoteAsString
		/// </summary>
		/// <returns></returns>
		public static string GetQuoteAsString(IQuote qu)
		{
			string quoteString = string.Empty;
			//string locDefaultExportDelimiter = Convert.ToString(defaultExportDelimiter);
			// DateTime

            string date = DateTimeUtil.CreateYearStringFourDigit(qu.DATE)
                + DateTimeUtil.CreateMonthStringTwoDigit(qu.DATE)
                + DateTimeUtil.CreateDayStringTwoDigit(qu.DATE);
			
			quoteString += date;

			// Open
			string openC = qu.OPENc.ToString(CUtil.Conversions.CultureCurrent);
			quoteString += defaultExportDelimiter;
			quoteString += openC;


            string highC = qu.HIGH.ToString(CUtil.Conversions.CultureCurrent);
			quoteString += defaultExportDelimiter;
			quoteString += highC;


            string lowC = qu.LOW.ToString(CUtil.Conversions.CultureCurrent);
			quoteString += defaultExportDelimiter;
			quoteString += lowC;

            string closeC = qu.CLOSEc.ToString(CUtil.Conversions.CultureCurrent);
			quoteString += defaultExportDelimiter;
			quoteString += closeC;

			// Volume
            string volC = qu.VOLUME.ToString(CUtil.Conversions.CultureCurrent);
			quoteString += defaultExportDelimiter;
			quoteString += volC;

			return quoteString;
		}
		public void CreateAllUpdates(DateTime dateStart, DateTime dateEnd)
		{
				
			for(int i = 0; i < this.programContext.TradeEconomy.Portfolios.Items.Count; i++)
			{
				IPortfolio port = this.programContext.TradeEconomy.Portfolios[i] as IPortfolio;
				port.RefreshShareData();

				for(int j = 0; j < port.DataItems.Count; j++)
				{
					DataClassDaily dcCurrent = port.DataItems[j].DataClass as DataClassDaily;
					CreateSingleShareUpdateDaily(dcCurrent, dateStart, dateEnd);

				}
			}		

		}
		private bool UpdateAll()
		{
				
			for(int i = 0; i < this.programContext.TradeEconomy.Portfolios.Items.Count; i++)
			{
				IPortfolio port = this.programContext.TradeEconomy.Portfolios[i] as IPortfolio;
				
				
				port.RefreshShareData();

				for(int j = 0; j < port.DataItems.Count; j++)
				{
					DataClassDaily dcCurrent = port.DataItems[j].DataClass as DataClassDaily;
					Debug.WriteLine("Updating " + dcCurrent.Name);
					UpdateShareDailiy(dcCurrent);

				}
			}
            return true;

		}

	
		private void UpdateShareDailiy(DataClassDaily dcCurrent)
		{
			
			
			DataClassDaily dcnew = dcCurrent.Clone() as DataClassDaily;
			((XMLSerializable)dcnew).Name = dcCurrent.Name;
			
			//IPortfolio port = this.programContextUpdate.TradeEconomy.Portfolios[0] as IPortfolio;

			ReadUpdateQuotes(dcnew);


			int iStartIndex = -1;

            DateTime lastTime = dcCurrent.QuoteCollection[dcCurrent.QuoteCollection.Count - 1].DATE;

            for (int i = 0; i < dcnew.QuoteCollection.Count; i++)
			{
				if(dcnew.SeriesTime[i] >= lastTime)
				{
					if(dcnew.SeriesTime[i].Day == lastTime.Day)
					{
						iStartIndex = i +1 ;
					}
					else
					{
						iStartIndex = i ;
					}
					break;
				}
			}


		
			

			//2. Update quotes

            IListQuotes qColl = dcnew.QuoteCollection;
			if(iStartIndex < 0 || iStartIndex >= dcnew.SeriesTime.Count)
				return;
			for(int i = iStartIndex; i < dcnew.SeriesTime.Count; i++)
			{
				IQuote qu = (IQuote)qColl[i];
				dcCurrent.SeriesVolume.Add(qu.VOLUME);
				dcCurrent.SeriesTime.Add(qu.DATE);
				dcCurrent.SeriesHigh.Add(qu.HIGH);
				dcCurrent.SeriesLow.Add(qu.LOW);
				dcCurrent.SeriesClose.Add(qu.CLOSEc);

			}
			try
			{
				
				string filePath = this.programContext.Configuration.Directories.QuotesDataPath;
				filePath = filePath + "\\" + ((IPortfolio)this.programContext.TradeEconomy.Portfolios[0]).Name;
				
				WriteQuotesToFile((DataClassDaily)dcCurrent);
				Debug.WriteLine("Create update file for share : " + dcCurrent.Name);
			}
			catch(Exception exc)
			{
				Debug.Assert(false,"Could not serialize share update " + dcnew.Name, exc.Message);
			}
		}
		private static void ReadUpdateQuotes(DataClassDaily dc)
		{
			object o = dc;
			if(! dc.DeSerialize(ref o))
			{
				//Debug.Assert(false,"Could not read quotes for " + dc.Name);
				System.Windows.Forms.MessageBox.Show("Could not update quotes for " + dc.Name + "; no data");
			}
		}
		private void CreateSingleShareUpdateDaily(DataClassDaily dcCurrent,DateTime dateStart, DateTime dateEnd)
		{
			
			
			DataClassDaily dcnew = dcCurrent.Clone() as DataClassDaily;
			((XMLSerializable)dcnew).Name = dcCurrent.Name;



            dcnew.SeriesTime = new List<DateTime>();
			dcnew.SeriesHigh = new List<double>();
			dcnew.SeriesLow = new List<double>();
			dcnew.SeriesClose = new List<double>();
			dcnew.SeriesLow = new List<double>();
            dcnew.SeriesVolume = new List<System.Int64>();


			//1. Find start end indexes
			int iStartIndex = -1;
			int iEndIndex = -1;

            IListQuotes qColl = dcCurrent.QuoteCollection;
			for(int i = qColl.Count -1; i >= 0; i--)
			{
				
				if(qColl[i].DATE < dateEnd)
				{
					if(qColl[i].DATE.Day == dateEnd.Day)
					{
						iEndIndex = i ;
					}
					else
					{
						iEndIndex = i + 1;
					}
					break;
				}
			

			}
			if(iEndIndex >= qColl.Count)
				iEndIndex = qColl.Count -1;
			
			for(int i = qColl.Count -1; i >= 0; i--)
			{
				if(qColl[i].DATE < dateStart)
				{
					if(qColl[i].DATE.Day == dateStart.Day)
					{
						iStartIndex = i ;
					}
					else
					{
						iStartIndex = i + 1;
					}
					
					break;
				}

			}
			if(iStartIndex >= qColl.Count)
				iStartIndex = qColl.Count -1;

			//2. Create quotes

			for(int i = iStartIndex; i <= iEndIndex; i++)
			{
				IQuote qu = (IQuote)qColl[i];
				dcnew.SeriesVolume.Add(qu.VOLUME);
				dcnew.SeriesTime.Add(qu.DATE);
				dcnew.SeriesHigh.Add(qu.HIGH);
				dcnew.SeriesLow.Add(qu.LOW);
				dcnew.SeriesClose.Add(qu.CLOSEc);

				
			}
			try
			{
				
				string filePath = this.programContextUpdate.Configuration.Directories.QuotesDataPath;
				filePath = filePath + "\\" + ((IPortfolio)this.programContext.TradeEconomy.Portfolios[0]).Name;
				WriteQuotesToFile((DataClassDaily)dcnew);
				Debug.WriteLine("Create update file for share : " + dcnew.Name);
			}
			catch(Exception exc)
			{
				Debug.Assert(false,"Could not serialize share update " + dcnew.Name, exc.Message);
			}
		}
		private string FindDir(DirectoryInfo dir)
		{
			foreach(DirectoryInfo subDir in dir.GetDirectories())
			{
				if(subDir.Name == "QuoteUpdate")
				{
					return subDir.FullName;
				}
				else
				{
					string str = FindDir(subDir) ;
					if(str != string.Empty)
					{
						return str;
					}
				}
			}
			return string.Empty;
		}
        //public void ExtractZipFiles()
        //{
        //    try
        //    {
        //        //create an update programContext
				

        //        ZipFilesCatalog zfc = new ZipFilesCatalog();
				
        //        try
        //        {
        //            zfc.CurrentFile = new ZipFile(this.programContextUpdate.Configuration.Directories.ApplicationPath + "\\" + this.programContextUpdate.Configuration.WebUpdateFileName);
        //        }
        //        catch(Exception e)
        //        {
        //            System.Windows.Forms.MessageBox.Show("Ther is no update file there !" + e.ToString());
        //        }
        //        if(zfc.CurrentFile != null)
        //        {
        //            ZipUtils.ExtractZipFile(zfc.CurrentFile, this.programContextUpdate.Configuration.Directories.ApplicationPath, null );
        //        }
        //    }
        //    catch(Exception exc)
        //    {
        //        Debug.Assert(false,"Error updating quotes", exc.Message);
        //    }
        //}
        //public void DownloadFile()
        //{
        //    WebFile wf = new WebFile();

        //    string fileName = this.programContext.Configuration.WebUpdateFileName;
        //    string fileWeb = this.programContext.Configuration.Directories.WebFilePath + fileName;
        //    string fileDisk = this.programContextUpdate.Configuration.Directories.ApplicationPath + "\\" + fileName;

        //    wf.GetFile(fileWeb,fileDisk);
        //}
		private string FindShareDirectory()
		{
			DirectoryInfo dir = new DirectoryInfo(this.programContextUpdate.Configuration.Directories.ApplicationPath);
			return this.FindDir(dir);

		}
		public bool UpdateQuotes(DateTime dateEnd )
		{
			string shareDir = FindShareDirectory();
            if (String.IsNullOrEmpty(shareDir))
            {
                System.Windows.Forms.MessageBox.Show("No directory found with update information ");
                return false;
            }

            string myID = "QuoteUpdate";
            string myPath = shareDir + "\\QuoteUpdate";

            this.programContextUpdate = CStock.ProgramContext.CreateProgramContext(myPath, myID, false);
            return UpdateAll();
            

		}

	}
}
